home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / tcltk / tcl8.5 / init.tcl < prev    next >
Encoding:
Text File  |  2009-11-22  |  24.4 KB  |  833 lines

  1. # init.tcl --
  2. #
  3. # Default system startup file for Tcl-based applications.  Defines
  4. # "unknown" procedure and auto-load facilities.
  5. #
  6. # RCS: @(#) $Id: init.tcl,v 1.104.2.13 2009/11/03 19:21:38 dgp Exp $
  7. #
  8. # Copyright (c) 1991-1993 The Regents of the University of California.
  9. # Copyright (c) 1994-1996 Sun Microsystems, Inc.
  10. # Copyright (c) 1998-1999 Scriptics Corporation.
  11. # Copyright (c) 2004 by Kevin B. Kenny.  All rights reserved.
  12. #
  13. # See the file "license.terms" for information on usage and redistribution
  14. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  15. #
  16.  
  17. if {[info commands package] == ""} {
  18.     error "version mismatch: library\nscripts expect Tcl version 7.5b1 or later but the loaded version is\nonly [info patchlevel]"
  19. }
  20. package require -exact Tcl 8.5.8
  21.  
  22. # Compute the auto path to use in this interpreter.
  23. # The values on the path come from several locations:
  24. #
  25. # The environment variable TCLLIBPATH
  26. #
  27. # tcl_library, which is the directory containing this init.tcl script.
  28. # [tclInit] (Tcl_Init()) searches around for the directory containing this
  29. # init.tcl and defines tcl_library to that location before sourcing it.
  30. #
  31. # The parent directory of tcl_library. Adding the parent
  32. # means that packages in peer directories will be found automatically.
  33. #
  34. # Also add the directory ../lib relative to the directory where the
  35. # executable is located.  This is meant to find binary packages for the
  36. # same architecture as the current executable.
  37. #
  38. # tcl_pkgPath, which is set by the platform-specific initialization routines
  39. #    On UNIX it is compiled in
  40. #       On Windows, it is not used
  41.  
  42. if {![info exists auto_path]} {
  43.     if {[info exists env(TCLLIBPATH)]} {
  44.     set auto_path $env(TCLLIBPATH)
  45.     } else {
  46.     set auto_path ""
  47.     }
  48. }
  49. namespace eval tcl {
  50.     variable Dir
  51.     foreach Dir [list $::tcl_library] {
  52.     if {$Dir ni $::auto_path} {
  53.         lappend ::auto_path $Dir
  54.     }
  55.     }
  56.     set Dir [file join [file dirname [file dirname \
  57.         [info nameofexecutable]]] lib]
  58.     if {$Dir ni $::auto_path} {
  59.     lappend ::auto_path $Dir
  60.     }
  61.     catch {
  62.     foreach Dir $::tcl_pkgPath {
  63.         if {$Dir ni $::auto_path} {
  64.         lappend ::auto_path $Dir
  65.         }
  66.     }
  67.     }
  68.  
  69.     if {![interp issafe]} {
  70.         variable Path [encoding dirs]
  71.         set Dir [file join $::tcl_library encoding]
  72.         if {$Dir ni $Path} {
  73.         lappend Path $Dir
  74.         encoding dirs $Path
  75.         }
  76.     }
  77.  
  78.     # TIP #255 min and max functions
  79.     namespace eval mathfunc {
  80.     proc min {args} {
  81.         if {[llength $args] == 0} {
  82.         return -code error \
  83.             "too few arguments to math function \"min\""
  84.         }
  85.         set val Inf
  86.         foreach arg $args {
  87.         # This will handle forcing the numeric value without
  88.         # ruining the internal type of a numeric object
  89.         if {[catch {expr {double($arg)}} err]} {
  90.             return -code error $err
  91.         }
  92.         if {$arg < $val} { set val $arg }
  93.         }
  94.         return $val
  95.     }
  96.     proc max {args} {
  97.         if {[llength $args] == 0} {
  98.         return -code error \
  99.             "too few arguments to math function \"max\""
  100.         }
  101.         set val -Inf
  102.         foreach arg $args {
  103.         # This will handle forcing the numeric value without
  104.         # ruining the internal type of a numeric object
  105.         if {[catch {expr {double($arg)}} err]} {
  106.             return -code error $err
  107.         }
  108.         if {$arg > $val} { set val $arg }
  109.         }
  110.         return $val
  111.     }
  112.     namespace export min max
  113.     }
  114. }
  115.  
  116. # Windows specific end of initialization
  117.  
  118. if {(![interp issafe]) && ($tcl_platform(platform) eq "windows")} {
  119.     namespace eval tcl {
  120.     proc EnvTraceProc {lo n1 n2 op} {
  121.         set x $::env($n2)
  122.         set ::env($lo) $x
  123.         set ::env([string toupper $lo]) $x
  124.     }
  125.     proc InitWinEnv {} {
  126.         global env tcl_platform
  127.         foreach p [array names env] {
  128.         set u [string toupper $p]
  129.         if {$u ne $p} {
  130.             switch -- $u {
  131.             COMSPEC -
  132.             PATH {
  133.                 if {![info exists env($u)]} {
  134.                 set env($u) $env($p)
  135.                 }
  136.                 trace add variable env($p) write \
  137.                     [namespace code [list EnvTraceProc $p]]
  138.                 trace add variable env($u) write \
  139.                     [namespace code [list EnvTraceProc $p]]
  140.             }
  141.             }
  142.         }
  143.         }
  144.         if {![info exists env(COMSPEC)]} {
  145.         if {$tcl_platform(os) eq "Windows NT"} {
  146.             set env(COMSPEC) cmd.exe
  147.         } else {
  148.             set env(COMSPEC) command.com
  149.         }
  150.         }
  151.     }
  152.     InitWinEnv
  153.     }
  154. }
  155.  
  156. # Setup the unknown package handler
  157.  
  158.  
  159. if {[interp issafe]} {
  160.     package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
  161. } else {
  162.     # Set up search for Tcl Modules (TIP #189).
  163.     # and setup platform specific unknown package handlers
  164.     if {$::tcl_platform(os) eq "Darwin"
  165.         && $::tcl_platform(platform) eq "unix"} {
  166.     package unknown {::tcl::tm::UnknownHandler \
  167.         {::tcl::MacOSXPkgUnknown ::tclPkgUnknown}}
  168.     } else {
  169.     package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
  170.     }
  171.  
  172.     # Set up the 'clock' ensemble
  173.  
  174.     namespace eval ::tcl::clock [list variable TclLibDir $::tcl_library]
  175.  
  176.     proc clock args {
  177.     namespace eval ::tcl::clock [list namespace ensemble create -command \
  178.         [uplevel 1 [list namespace origin [lindex [info level 0] 0]]] \
  179.         -subcommands {
  180.             add clicks format microseconds milliseconds scan seconds
  181.         }]
  182.     
  183.     # Auto-loading stubs for 'clock.tcl'
  184.     
  185.     foreach cmd {add format scan} {
  186.         proc ::tcl::clock::$cmd args {
  187.         variable TclLibDir
  188.         source -encoding utf-8 [file join $TclLibDir clock.tcl]
  189.         return [uplevel 1 [info level 0]]
  190.         }
  191.     }
  192.  
  193.     return [uplevel 1 [info level 0]]
  194.     }
  195. }
  196.  
  197. # Conditionalize for presence of exec.
  198.  
  199. if {[namespace which -command exec] eq ""} {
  200.  
  201.     # Some machines do not have exec. Also, on all
  202.     # platforms, safe interpreters do not have exec.
  203.  
  204.     set auto_noexec 1
  205. }
  206.  
  207. # Define a log command (which can be overwitten to log errors
  208. # differently, specially when stderr is not available)
  209.  
  210. if {[namespace which -command tclLog] eq ""} {
  211.     proc tclLog {string} {
  212.     catch {puts stderr $string}
  213.     }
  214. }
  215.  
  216. # unknown --
  217. # This procedure is called when a Tcl command is invoked that doesn't
  218. # exist in the interpreter.  It takes the following steps to make the
  219. # command available:
  220. #
  221. #    1. See if the command has the form "namespace inscope ns cmd" and
  222. #       if so, concatenate its arguments onto the end and evaluate it.
  223. #    2. See if the autoload facility can locate the command in a
  224. #       Tcl script file.  If so, load it and execute it.
  225. #    3. If the command was invoked interactively at top-level:
  226. #        (a) see if the command exists as an executable UNIX program.
  227. #        If so, "exec" the command.
  228. #        (b) see if the command requests csh-like history substitution
  229. #        in one of the common forms !!, !<number>, or ^old^new.  If
  230. #        so, emulate csh's history substitution.
  231. #        (c) see if the command is a unique abbreviation for another
  232. #        command.  If so, invoke the command.
  233. #
  234. # Arguments:
  235. # args -    A list whose elements are the words of the original
  236. #        command, including the command name.
  237.  
  238. proc unknown args {
  239.     variable ::tcl::UnknownPending
  240.     global auto_noexec auto_noload env tcl_interactive
  241.  
  242.     # If the command word has the form "namespace inscope ns cmd"
  243.     # then concatenate its arguments onto the end and evaluate it.
  244.  
  245.     set cmd [lindex $args 0]
  246.     if {[regexp "^:*namespace\[ \t\n\]+inscope" $cmd] && [llength $cmd] == 4} {
  247.     #return -code error "You need an {*}"
  248.         set arglist [lrange $args 1 end]
  249.     set ret [catch {uplevel 1 ::$cmd $arglist} result opts]
  250.     dict unset opts -errorinfo
  251.     dict incr opts -level
  252.     return -options $opts $result
  253.     }
  254.  
  255.     catch {set savedErrorInfo $::errorInfo}
  256.     catch {set savedErrorCode $::errorCode}
  257.     set name $cmd
  258.     if {![info exists auto_noload]} {
  259.     #
  260.     # Make sure we're not trying to load the same proc twice.
  261.     #
  262.     if {[info exists UnknownPending($name)]} {
  263.         return -code error "self-referential recursion\
  264.             in \"unknown\" for command \"$name\"";
  265.     }
  266.     set UnknownPending($name) pending;
  267.     set ret [catch {
  268.         auto_load $name [uplevel 1 {::namespace current}]
  269.     } msg opts]
  270.     unset UnknownPending($name);
  271.     if {$ret != 0} {
  272.         dict append opts -errorinfo "\n    (autoloading \"$name\")"
  273.         return -options $opts $msg
  274.     }
  275.     if {![array size UnknownPending]} {
  276.         unset UnknownPending
  277.     }
  278.     if {$msg} {
  279.         if {[info exists savedErrorCode]} {
  280.         set ::errorCode $savedErrorCode
  281.         } else {
  282.         unset -nocomplain ::errorCode
  283.         }
  284.         if {[info exists savedErrorInfo]} {
  285.         set ::errorInfo $savedErrorInfo
  286.         } else {
  287.         unset -nocomplain ::errorInfo
  288.         }
  289.         set code [catch {uplevel 1 $args} msg opts]
  290.         if {$code ==  1} {
  291.         #
  292.         # Compute stack trace contribution from the [uplevel].
  293.         # Note the dependence on how Tcl_AddErrorInfo, etc. 
  294.         # construct the stack trace.
  295.         #
  296.         set errorInfo [dict get $opts -errorinfo]
  297.         set errorCode [dict get $opts -errorcode]
  298.         set cinfo $args
  299.         if {[string bytelength $cinfo] > 150} {
  300.             set cinfo [string range $cinfo 0 150]
  301.             while {[string bytelength $cinfo] > 150} {
  302.             set cinfo [string range $cinfo 0 end-1]
  303.             }
  304.             append cinfo ...
  305.         }
  306.         append cinfo "\"\n    (\"uplevel\" body line 1)"
  307.         append cinfo "\n    invoked from within"
  308.         append cinfo "\n\"uplevel 1 \$args\""
  309.         #
  310.         # Try each possible form of the stack trace
  311.         # and trim the extra contribution from the matching case
  312.         #
  313.         set expect "$msg\n    while executing\n\"$cinfo"
  314.         if {$errorInfo eq $expect} {
  315.             #
  316.             # The stack has only the eval from the expanded command
  317.             # Do not generate any stack trace here.
  318.             #
  319.             dict unset opts -errorinfo
  320.             dict incr opts -level
  321.             return -options $opts $msg
  322.         }
  323.         #
  324.         # Stack trace is nested, trim off just the contribution
  325.         # from the extra "eval" of $args due to the "catch" above.
  326.         #
  327.         set expect "\n    invoked from within\n\"$cinfo"
  328.         set exlen [string length $expect]
  329.         set eilen [string length $errorInfo]
  330.         set i [expr {$eilen - $exlen - 1}]
  331.         set einfo [string range $errorInfo 0 $i]
  332.         #
  333.         # For now verify that $errorInfo consists of what we are about
  334.         # to return plus what we expected to trim off.
  335.         #
  336.         if {$errorInfo ne "$einfo$expect"} {
  337.             error "Tcl bug: unexpected stack trace in \"unknown\"" {} \
  338.             [list CORE UNKNOWN BADTRACE $einfo $expect $errorInfo]
  339.         }
  340.         return -code error -errorcode $errorCode \
  341.             -errorinfo $einfo $msg
  342.         } else {
  343.         dict incr opts -level
  344.         return -options $opts $msg
  345.         }
  346.     }
  347.     }
  348.  
  349.     if {([info level] == 1) && ([info script] eq "") \
  350.         && [info exists tcl_interactive] && $tcl_interactive} {
  351.     if {![info exists auto_noexec]} {
  352.         set new [auto_execok $name]
  353.         if {$new ne ""} {
  354.         set redir ""
  355.         if {[namespace which -command console] eq ""} {
  356.             set redir ">&@stdout <@stdin"
  357.         }
  358.         uplevel 1 [list ::catch \
  359.             [concat exec $redir $new [lrange $args 1 end]] \
  360.             ::tcl::UnknownResult ::tcl::UnknownOptions]
  361.         dict incr ::tcl::UnknownOptions -level
  362.         return -options $::tcl::UnknownOptions $::tcl::UnknownResult
  363.         }
  364.     }
  365.     if {$name eq "!!"} {
  366.         set newcmd [history event]
  367.     } elseif {[regexp {^!(.+)$} $name -> event]} {
  368.         set newcmd [history event $event]
  369.     } elseif {[regexp {^\^([^^]*)\^([^^]*)\^?$} $name -> old new]} {
  370.         set newcmd [history event -1]
  371.         catch {regsub -all -- $old $newcmd $new newcmd}
  372.     }
  373.     if {[info exists newcmd]} {
  374.         tclLog $newcmd
  375.         history change $newcmd 0
  376.         uplevel 1 [list ::catch $newcmd \
  377.             ::tcl::UnknownResult ::tcl::UnknownOptions]
  378.         dict incr ::tcl::UnknownOptions -level
  379.         return -options $::tcl::UnknownOptions $::tcl::UnknownResult
  380.     }
  381.  
  382.     set ret [catch {set candidates [info commands $name*]} msg]
  383.     if {$name eq "::"} {
  384.         set name ""
  385.     }
  386.     if {$ret != 0} {
  387.         dict append opts -errorinfo \
  388.             "\n    (expanding command prefix \"$name\" in unknown)"
  389.         return -options $opts $msg
  390.     }
  391.     # Filter out bogus matches when $name contained
  392.     # a glob-special char [Bug 946952]
  393.     if {$name eq ""} {
  394.         # Handle empty $name separately due to strangeness
  395.         # in [string first] (See RFE 1243354)
  396.         set cmds $candidates
  397.     } else {
  398.         set cmds [list]
  399.         foreach x $candidates {
  400.         if {[string first $name $x] == 0} {
  401.             lappend cmds $x
  402.         }
  403.         }
  404.     }
  405.     if {[llength $cmds] == 1} {
  406.         uplevel 1 [list ::catch [lreplace $args 0 0 [lindex $cmds 0]] \
  407.             ::tcl::UnknownResult ::tcl::UnknownOptions]
  408.         dict incr ::tcl::UnknownOptions -level
  409.         return -options $::tcl::UnknownOptions $::tcl::UnknownResult
  410.     }
  411.     if {[llength $cmds]} {
  412.         return -code error "ambiguous command name \"$name\": [lsort $cmds]"
  413.     }
  414.     }
  415.     return -code error "invalid command name \"$name\""
  416. }
  417.  
  418. # auto_load --
  419. # Checks a collection of library directories to see if a procedure
  420. # is defined in one of them.  If so, it sources the appropriate
  421. # library file to create the procedure.  Returns 1 if it successfully
  422. # loaded the procedure, 0 otherwise.
  423. #
  424. # Arguments: 
  425. # cmd -            Name of the command to find and load.
  426. # namespace (optional)  The namespace where the command is being used - must be
  427. #                       a canonical namespace as returned [namespace current]
  428. #                       for instance. If not given, namespace current is used.
  429.  
  430. proc auto_load {cmd {namespace {}}} {
  431.     global auto_index auto_path
  432.  
  433.     if {$namespace eq ""} {
  434.     set namespace [uplevel 1 [list ::namespace current]]
  435.     }
  436.     set nameList [auto_qualify $cmd $namespace]
  437.     # workaround non canonical auto_index entries that might be around
  438.     # from older auto_mkindex versions
  439.     lappend nameList $cmd
  440.     foreach name $nameList {
  441.     if {[info exists auto_index($name)]} {
  442.         namespace eval :: $auto_index($name)
  443.         # There's a couple of ways to look for a command of a given
  444.         # name.  One is to use
  445.         #    info commands $name
  446.         # Unfortunately, if the name has glob-magic chars in it like *
  447.         # or [], it may not match.  For our purposes here, a better
  448.         # route is to use 
  449.         #    namespace which -command $name
  450.         if {[namespace which -command $name] ne ""} {
  451.         return 1
  452.         }
  453.     }
  454.     }
  455.     if {![info exists auto_path]} {
  456.     return 0
  457.     }
  458.  
  459.     if {![auto_load_index]} {
  460.     return 0
  461.     }
  462.     foreach name $nameList {
  463.     if {[info exists auto_index($name)]} {
  464.         namespace eval :: $auto_index($name)
  465.         if {[namespace which -command $name] ne ""} {
  466.         return 1
  467.         }
  468.     }
  469.     }
  470.     return 0
  471. }
  472.  
  473. # auto_load_index --
  474. # Loads the contents of tclIndex files on the auto_path directory
  475. # list.  This is usually invoked within auto_load to load the index
  476. # of available commands.  Returns 1 if the index is loaded, and 0 if
  477. # the index is already loaded and up to date.
  478. #
  479. # Arguments: 
  480. # None.
  481.  
  482. proc auto_load_index {} {
  483.     variable ::tcl::auto_oldpath
  484.     global auto_index auto_path
  485.  
  486.     if {[info exists auto_oldpath] && ($auto_oldpath eq $auto_path)} {
  487.     return 0
  488.     }
  489.     set auto_oldpath $auto_path
  490.  
  491.     # Check if we are a safe interpreter. In that case, we support only
  492.     # newer format tclIndex files.
  493.  
  494.     set issafe [interp issafe]
  495.     for {set i [expr {[llength $auto_path] - 1}]} {$i >= 0} {incr i -1} {
  496.     set dir [lindex $auto_path $i]
  497.     set f ""
  498.     if {$issafe} {
  499.         catch {source [file join $dir tclIndex]}
  500.     } elseif {[catch {set f [open [file join $dir tclIndex]]}]} {
  501.         continue
  502.     } else {
  503.         set error [catch {
  504.         set id [gets $f]
  505.         if {$id eq "# Tcl autoload index file, version 2.0"} {
  506.             eval [read $f]
  507.         } elseif {$id eq "# Tcl autoload index file: each line identifies a Tcl"} {
  508.             while {[gets $f line] >= 0} {
  509.             if {([string index $line 0] eq "#") \
  510.                 || ([llength $line] != 2)} {
  511.                 continue
  512.             }
  513.             set name [lindex $line 0]
  514.             set auto_index($name) \
  515.                 "source [file join $dir [lindex $line 1]]"
  516.             }
  517.         } else {
  518.             error "[file join $dir tclIndex] isn't a proper Tcl index file"
  519.         }
  520.         } msg opts]
  521.         if {$f ne ""} {
  522.         close $f
  523.         }
  524.         if {$error} {
  525.         return -options $opts $msg
  526.         }
  527.     }
  528.     }
  529.     return 1
  530. }
  531.  
  532. # auto_qualify --
  533. #
  534. # Compute a fully qualified names list for use in the auto_index array.
  535. # For historical reasons, commands in the global namespace do not have leading
  536. # :: in the index key. The list has two elements when the command name is
  537. # relative (no leading ::) and the namespace is not the global one. Otherwise
  538. # only one name is returned (and searched in the auto_index).
  539. #
  540. # Arguments -
  541. # cmd        The command name. Can be any name accepted for command
  542. #               invocations (Like "foo::::bar").
  543. # namespace    The namespace where the command is being used - must be
  544. #               a canonical namespace as returned by [namespace current]
  545. #               for instance.
  546.  
  547. proc auto_qualify {cmd namespace} {
  548.  
  549.     # count separators and clean them up
  550.     # (making sure that foo:::::bar will be treated as foo::bar)
  551.     set n [regsub -all {::+} $cmd :: cmd]
  552.  
  553.     # Ignore namespace if the name starts with ::
  554.     # Handle special case of only leading ::
  555.  
  556.     # Before each return case we give an example of which category it is
  557.     # with the following form :
  558.     # ( inputCmd, inputNameSpace) -> output
  559.  
  560.     if {[string match ::* $cmd]} {
  561.     if {$n > 1} {
  562.         # ( ::foo::bar , * ) -> ::foo::bar
  563.         return [list $cmd]
  564.     } else {
  565.         # ( ::global , * ) -> global
  566.         return [list [string range $cmd 2 end]]
  567.     }
  568.     }
  569.     
  570.     # Potentially returning 2 elements to try  :
  571.     # (if the current namespace is not the global one)
  572.  
  573.     if {$n == 0} {
  574.     if {$namespace eq "::"} {
  575.         # ( nocolons , :: ) -> nocolons
  576.         return [list $cmd]
  577.     } else {
  578.         # ( nocolons , ::sub ) -> ::sub::nocolons nocolons
  579.         return [list ${namespace}::$cmd $cmd]
  580.     }
  581.     } elseif {$namespace eq "::"} {
  582.     #  ( foo::bar , :: ) -> ::foo::bar
  583.     return [list ::$cmd]
  584.     } else {
  585.     # ( foo::bar , ::sub ) -> ::sub::foo::bar ::foo::bar
  586.     return [list ${namespace}::$cmd ::$cmd]
  587.     }
  588. }
  589.  
  590. # auto_import --
  591. #
  592. # Invoked during "namespace import" to make see if the imported commands
  593. # reside in an autoloaded library.  If so, the commands are loaded so
  594. # that they will be available for the import links.  If not, then this
  595. # procedure does nothing.
  596. #
  597. # Arguments -
  598. # pattern    The pattern of commands being imported (like "foo::*")
  599. #               a canonical namespace as returned by [namespace current]
  600.  
  601. proc auto_import {pattern} {
  602.     global auto_index
  603.  
  604.     # If no namespace is specified, this will be an error case
  605.  
  606.     if {![string match *::* $pattern]} {
  607.     return
  608.     }
  609.  
  610.     set ns [uplevel 1 [list ::namespace current]]
  611.     set patternList [auto_qualify $pattern $ns]
  612.  
  613.     auto_load_index
  614.  
  615.     foreach pattern $patternList {
  616.         foreach name [array names auto_index $pattern] {
  617.             if {([namespace which -command $name] eq "")
  618.             && ([namespace qualifiers $pattern] eq [namespace qualifiers $name])} {
  619.                 namespace eval :: $auto_index($name)
  620.             }
  621.         }
  622.     }
  623. }
  624.  
  625. # auto_execok --
  626. #
  627. # Returns string that indicates name of program to execute if 
  628. # name corresponds to a shell builtin or an executable in the
  629. # Windows search path, or "" otherwise.  Builds an associative 
  630. # array auto_execs that caches information about previous checks, 
  631. # for speed.
  632. #
  633. # Arguments: 
  634. # name -            Name of a command.
  635.  
  636. if {$tcl_platform(platform) eq "windows"} {
  637. # Windows version.
  638. #
  639. # Note that info executable doesn't work under Windows, so we have to
  640. # look for files with .exe, .com, or .bat extensions.  Also, the path
  641. # may be in the Path or PATH environment variables, and path
  642. # components are separated with semicolons, not colons as under Unix.
  643. #
  644. proc auto_execok name {
  645.     global auto_execs env tcl_platform
  646.  
  647.     if {[info exists auto_execs($name)]} {
  648.     return $auto_execs($name)
  649.     }
  650.     set auto_execs($name) ""
  651.  
  652.     set shellBuiltins [list cls copy date del erase dir echo mkdir \
  653.         md rename ren rmdir rd time type ver vol]
  654.     if {$tcl_platform(os) eq "Windows NT"} {
  655.     # NT includes the 'start' built-in
  656.     lappend shellBuiltins "start"
  657.     }
  658.     if {[info exists env(PATHEXT)]} {
  659.     # Add an initial ; to have the {} extension check first.
  660.     set execExtensions [split ";$env(PATHEXT)" ";"]
  661.     } else {
  662.     set execExtensions [list {} .com .exe .bat]
  663.     }
  664.  
  665.     if {$name in $shellBuiltins} {
  666.     # When this is command.com for some reason on Win2K, Tcl won't
  667.     # exec it unless the case is right, which this corrects.  COMSPEC
  668.     # may not point to a real file, so do the check.
  669.     set cmd $env(COMSPEC)
  670.     if {[file exists $cmd]} {
  671.         set cmd [file attributes $cmd -shortname]
  672.     }
  673.     return [set auto_execs($name) [list $cmd /c $name]]
  674.     }
  675.  
  676.     if {[llength [file split $name]] != 1} {
  677.     foreach ext $execExtensions {
  678.         set file ${name}${ext}
  679.         if {[file exists $file] && ![file isdirectory $file]} {
  680.         return [set auto_execs($name) [list $file]]
  681.         }
  682.     }
  683.     return ""
  684.     }
  685.  
  686.     set path "[file dirname [info nameof]];.;"
  687.     if {[info exists env(WINDIR)]} {
  688.     set windir $env(WINDIR) 
  689.     }
  690.     if {[info exists windir]} {
  691.     if {$tcl_platform(os) eq "Windows NT"} {
  692.         append path "$windir/system32;"
  693.     }
  694.     append path "$windir/system;$windir;"
  695.     }
  696.  
  697.     foreach var {PATH Path path} {
  698.     if {[info exists env($var)]} {
  699.         append path ";$env($var)"
  700.     }
  701.     }
  702.  
  703.     foreach dir [split $path {;}] {
  704.     # Skip already checked directories
  705.     if {[info exists checked($dir)] || ($dir eq {})} { continue }
  706.     set checked($dir) {}
  707.     foreach ext $execExtensions {
  708.         set file [file join $dir ${name}${ext}]
  709.         if {[file exists $file] && ![file isdirectory $file]} {
  710.         return [set auto_execs($name) [list $file]]
  711.         }
  712.     }
  713.     }
  714.     return ""
  715. }
  716.  
  717. } else {
  718. # Unix version.
  719. #
  720. proc auto_execok name {
  721.     global auto_execs env
  722.  
  723.     if {[info exists auto_execs($name)]} {
  724.     return $auto_execs($name)
  725.     }
  726.     set auto_execs($name) ""
  727.     if {[llength [file split $name]] != 1} {
  728.     if {[file executable $name] && ![file isdirectory $name]} {
  729.         set auto_execs($name) [list $name]
  730.     }
  731.     return $auto_execs($name)
  732.     }
  733.     foreach dir [split $env(PATH) :] {
  734.     if {$dir eq ""} {
  735.         set dir .
  736.     }
  737.     set file [file join $dir $name]
  738.     if {[file executable $file] && ![file isdirectory $file]} {
  739.         set auto_execs($name) [list $file]
  740.         return $auto_execs($name)
  741.     }
  742.     }
  743.     return ""
  744. }
  745.  
  746. }
  747.  
  748. # ::tcl::CopyDirectory --
  749. #
  750. # This procedure is called by Tcl's core when attempts to call the
  751. # filesystem's copydirectory function fail.  The semantics of the call
  752. # are that 'dest' does not yet exist, i.e. dest should become the exact
  753. # image of src.  If dest does exist, we throw an error.  
  754. # Note that making changes to this procedure can change the results
  755. # of running Tcl's tests.
  756. #
  757. # Arguments: 
  758. # action -              "renaming" or "copying" 
  759. # src -            source directory
  760. # dest -        destination directory
  761. proc tcl::CopyDirectory {action src dest} {
  762.     set nsrc [file normalize $src]
  763.     set ndest [file normalize $dest]
  764.  
  765.     if {$action eq "renaming"} {
  766.     # Can't rename volumes.  We could give a more precise
  767.     # error message here, but that would break the test suite.
  768.     if {$nsrc in [file volumes]} {
  769.         return -code error "error $action \"$src\" to\
  770.           \"$dest\": trying to rename a volume or move a directory\
  771.           into itself"
  772.     }
  773.     }
  774.     if {[file exists $dest]} {
  775.     if {$nsrc eq $ndest} {
  776.         return -code error "error $action \"$src\" to\
  777.           \"$dest\": trying to rename a volume or move a directory\
  778.           into itself"
  779.     }
  780.     if {$action eq "copying"} {
  781.         # We used to throw an error here, but, looking more closely
  782.         # at the core copy code in tclFCmd.c, if the destination
  783.         # exists, then we should only call this function if -force
  784.         # is true, which means we just want to over-write.  So,
  785.         # the following code is now commented out.
  786.         # 
  787.         # return -code error "error $action \"$src\" to\
  788.         # \"$dest\": file already exists"
  789.     } else {
  790.         # Depending on the platform, and on the current
  791.         # working directory, the directories '.', '..'
  792.         # can be returned in various combinations.  Anyway,
  793.         # if any other file is returned, we must signal an error.
  794.         set existing [glob -nocomplain -directory $dest * .*]
  795.         lappend existing {*}[glob -nocomplain -directory $dest \
  796.             -type hidden * .*]
  797.         foreach s $existing {
  798.         if {([file tail $s] ne ".") && ([file tail $s] ne "..")} {
  799.             return -code error "error $action \"$src\" to\
  800.               \"$dest\": file already exists"
  801.         }
  802.         }
  803.     }
  804.     } else {
  805.     if {[string first $nsrc $ndest] != -1} {
  806.         set srclen [expr {[llength [file split $nsrc]] -1}]
  807.         set ndest [lindex [file split $ndest] $srclen]
  808.         if {$ndest eq [file tail $nsrc]} {
  809.         return -code error "error $action \"$src\" to\
  810.           \"$dest\": trying to rename a volume or move a directory\
  811.           into itself"
  812.         }
  813.     }
  814.     file mkdir $dest
  815.     }
  816.     # Have to be careful to capture both visible and hidden files.
  817.     # We will also be more generous to the file system and not
  818.     # assume the hidden and non-hidden lists are non-overlapping.
  819.     # 
  820.     # On Unix 'hidden' files begin with '.'.  On other platforms
  821.     # or filesystems hidden files may have other interpretations.
  822.     set filelist [concat [glob -nocomplain -directory $src *] \
  823.       [glob -nocomplain -directory $src -types hidden *]]
  824.  
  825.     foreach s [lsort -unique $filelist] {
  826.     if {([file tail $s] ne ".") && ([file tail $s] ne "..")} {
  827.         file copy -force $s [file join $dest [file tail $s]]
  828.     }
  829.     }
  830.     return
  831. }
  832.